package com.iflytek.edu.db.agent.transformer;

import com.iflytek.edu.db.agent.utils.PrintUtils;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import lombok.extern.slf4j.Slf4j;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.Objects;

/**
 * mybatis: RoutingStatementHandler 拦截
 */
@Slf4j
public class MybatisTransformer implements ClassFileTransformer {

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classFileBuffer) throws IllegalClassFormatException {
        log.debug("agent premain load Class: {}", className);
        if (Objects.equals(className, "org/apache/ibatis/executor/statement/RoutingStatementHandler")) {
            // 获取classPool
            ClassPool classPool = ClassPool.getDefault();
            try {
                // 获取Class
                CtClass clazz = classPool.get("org.apache.ibatis.executor.statement.RoutingStatementHandler");
                // 获取方法
                CtMethod method = clazz.getDeclaredMethod("prepare");
                // 在方法执行前
                method.insertBefore(
                        "org.apache.ibatis.mapping.BoundSql boundSql = getBoundSql();\n" +
                                "// 获取到原始sql语句\n" +
                                "String sql = boundSql.getSql();\n" +
                                "// 适配SQL\n" +
                                "sql = com.iflytek.edu.db.agent.utils.SqlAdapterUtils.adapter(sql);\n" +
                                "// 通过反射修改sql语句\n" +
                                "cn.hutool.core.util.ReflectUtil.setFieldValue(boundSql, \"sql\", sql);\n");
                // 打印信息
                PrintUtils.printMethodInfo(clazz, method);
                // 返回字节码，并且detachCtClass对象
                return clazz.toBytecode();
            } catch (Exception e) {
                log.error("agent adapter ", e);
            }
        }
        return classFileBuffer;
    }

}
